use std::collections::HashMap;
use std::sync::LazyLock;

#[must_use]
pub fn converter(input: &str, tp: &str) -> String {
    match tp {
        "s2t" => convert(input, &S2T_PHRASE_TABLE, &S2T_CHAR_TABLE),
        "t2s" => convert(input, &T2S_PHRASE_TABLE, &T2S_CHAR_TABLE),
        _ => panic!("Invalid type"),
    }
}

fn convert(input: &str, phrase_table: &PhraseTable, char_table: &CharTable) -> String {
    if let Some(values) = phrase_table.get(input) {
        if let Some(first) = values.first().copied() {
            return first.to_owned();
        }
    }

    let mut ans = String::new();
    for c in input.chars() {
        if let Some(values) = char_table.get(&c) {
            if let Some(first) = values.first().copied() {
                ans.push(first);
            } else {
                ans.push(c);
            }
        } else {
            ans.push(c);
        }
    }

    ans
}

type PhraseTable = HashMap<&'static str, Vec<&'static str>>;

type CharTable = HashMap<char, Vec<char>>;

fn load_phrase_table(file_content: &'static str) -> PhraseTable {
    let mut ans = HashMap::new();
    for line in file_content.lines() {
        let (key, values) = line.split_once(':').unwrap();
        let values = values.split(' ').collect();
        ans.insert(key, values);
    }
    ans
}

fn load_char_table(file_content: &str) -> CharTable {
    let mut ans = HashMap::new();
    for line in file_content.lines() {
        let (key, values) = line.split_once(':').unwrap();
        let key = key.chars().next().unwrap();
        let values = values
            .split(' ')
            .map(|c| c.chars().next().unwrap())
            .collect();
        ans.insert(key, values);
    }
    ans
}

static S2T_PHRASE_TABLE: LazyLock<PhraseTable> =
    LazyLock::new(|| load_phrase_table(include_str!(concat!(env!("OUT_DIR"), "/s2t_phrases.txt"))));

static S2T_CHAR_TABLE: LazyLock<CharTable> =
    LazyLock::new(|| load_char_table(include_str!(concat!(env!("OUT_DIR"), "/s2t_chars.txt"))));

static T2S_PHRASE_TABLE: LazyLock<PhraseTable> =
    LazyLock::new(|| load_phrase_table(include_str!(concat!(env!("OUT_DIR"), "/t2s_phrases.txt"))));

static T2S_CHAR_TABLE: LazyLock<CharTable> =
    LazyLock::new(|| load_char_table(include_str!(concat!(env!("OUT_DIR"), "/t2s_chars.txt"))));
